#include "matchroom.h"
#include "algorithm"
#include "db/dbmanager.h"
#include "utils/encodetool.h"
#include "log.h"

static Logger::ptr lvqiang = LoggerMgr::GetInstance()->GetLogger("lvqiang");

MatchRoom::MatchRoom(int roomId)
{
    m_roomId = roomId;
    m_remainSeats.push_back(proto::SeatPosition::Left);
    m_remainSeats.push_back(proto::SeatPosition::Middle);
    m_remainSeats.push_back(proto::SeatPosition::Right);
}

proto::RoomType MatchRoom::GetRoomType()
{
    return m_roomType;
}

void MatchRoom::SetRoomType(proto::RoomType roomType)
{
    m_roomType = roomType;
}

int MatchRoom::GetRoomId()
{
    return m_roomId;
}

bool MatchRoom::IsFull()
{
    return m_players.size() == 3;
}

bool MatchRoom::IsAllReady()
{
    return m_alreadyPlayers.size() == 3;
}

void MatchRoom::Enter(Player::ptr& player)
{
    return m_players.push_front(player);
}

void MatchRoom::Leave(int playerId)
{
    auto it = m_players.begin();
    while(it != m_players.end())
    {
        if((*it)->GetId() == playerId)
        {
            m_players.erase(it);
            break;
        }
        it++;
    }
    auto it1 = m_alreadyPlayers.begin();
    while(it1 != m_alreadyPlayers.end())
    {
        if((*it1) == playerId)
        {
            m_alreadyPlayers.erase(it1);
            break;
        }
        it1++;
    }
}

bool MatchRoom::IsReady(int playerId)
{
    return std::count(m_alreadyPlayers.begin(), m_alreadyPlayers.end(), playerId) > 0;
}

void MatchRoom::Ready(int playerId)
{
    if(std::count(m_alreadyPlayers.begin(), m_alreadyPlayers.end(), playerId) == 0)
    {
        m_alreadyPlayers.push_back(playerId);
    }  
}

void MatchRoom::CancelReady(int playerId)
{
    auto it1 = m_alreadyPlayers.begin();
    while(it1 != m_alreadyPlayers.end())
    {
        if(*it1 == playerId)
        {
            m_alreadyPlayers.erase(it1);
            break;
        }
        it1++;
    }
}

proto::SeatPosition MatchRoom::DistributionSeat()
{
    proto::SeatPosition seatPosition;
    seatPosition = m_remainSeats[0];
    m_remainSeats.erase(m_remainSeats.begin());
    return seatPosition;
}

void MatchRoom::RecycleSeat(proto::SeatPosition seatpostion)
{
    m_remainSeats.push_back(seatpostion);
}



void MatchRoom::BroadCast(proto::NetMsg& netMsg, bool isContainSelf, Player::ptr& player)
{
    //将netMsg广播给所有玩家
    if(isContainSelf)
    {
        for(auto tplayer : m_players)
        {
            EnCodeTool::EnCode(netMsg, tplayer->GetSocket()->GetSendBuf());
            tplayer->GetSocket()->Send();
        }
    }
    //将netMsg广播给除自身以外的所有玩家
    else
    {
        for(auto tplayer : m_players)
        {
            if(!(tplayer == player))
            {
                EnCodeTool::EnCode(netMsg, tplayer->GetSocket()->GetSendBuf());
                tplayer->GetSocket()->Send();
            }
        }
    }
}

void MatchRoom::PickBanker()
{
    int num = std::rand() % 3;
    auto it = m_players.begin();
    for(int i = 0; i < num; i++)
    {
        it++;
    }
    m_banker = (*it);
}

void MatchRoom::DealCard()
{
    auto it = m_players.begin();
    for(int i = 0; i < 3; i++)
    {
        for(int j = 0; j < 3; j++)
        {

            (*it)->AddCard(CardMgr::GetInstance()->DealCard());
        }
        it++;
    }
}

void MatchRoom::SortCard()
{
    auto it = m_players.begin();
    while(it != m_players.end())
    {
        std::vector<Card::ptr>& cards = (*it)->GetCards();
        for (size_t i = 0; i < cards.size(); i++)
        {
            for (size_t j = 0; j < cards.size() - 1 - i; j++)
            {
                if(cards[j]->GetWeight() < cards[j+1]->GetWeight())
                {
                    Card::ptr tmp = cards[j];
                    cards[j] = cards[j + 1];
                    cards[j + 1] = cards[j];
                }
            }
        }  
        it++;
    }
}

void MatchRoom::GetCardType()
{
    auto it = m_players.begin();
    while(it != m_players.end())
    {
        std::vector<Card::ptr>& cards = (*it)->GetCards();
        if(cards[0]->GetWeight() == 5 && cards[1]->GetWeight() == 3 && cards[2]->GetWeight() == 2)
        {
            (*it)->SetCardType(proto::CardType::Max);
        }
        else if(cards[0]->GetWeight() == cards[1]->GetWeight() && cards[1]->GetWeight() == cards[2]->GetWeight())
        {
            (*it)->SetCardType(proto::CardType::Baozi);
        }
        else if(cards[0]->GetColor() == cards[1]->GetColor() && cards[0]->GetColor() == cards[1]->GetColor() &&
                cards[0]->GetWeight() == cards[1]->GetWeight() + 1 && cards[0]->GetWeight() == cards[2]->GetWeight())
        {
            (*it)->SetCardType(proto::CardType::Shunjin);
        }
        else if(cards[0]->GetColor() == cards[1]->GetColor() && cards[0]->GetColor() == cards[1]->GetColor())
        {
            (*it)->SetCardType(proto::CardType::Jinhua);
        }
        else if(cards[0]->GetWeight() == cards[1]->GetWeight() + 1 && cards[0]->GetWeight() == cards[2]->GetWeight())
        {
            (*it)->SetCardType(proto::CardType::Shunzi);
        }
        else if(cards[0]->GetWeight() == cards[1]->GetWeight() || cards[0]->GetWeight() == cards[2]->GetWeight() || 
                cards[1]->GetWeight() == cards[2]->GetWeight())
        {
            (*it)->SetCardType(proto::CardType::Duizi);
        }
        else
        {
            (*it)->SetCardType(proto::CardType::Min);
        }
        it++;
    }
}

Player::ptr& MatchRoom::GetNextPlayer(proto::SeatPosition seatPosition)
{
    if(seatPosition == proto::SeatPosition::Middle)
    {
        auto it = m_players.begin();
        while(it != m_players.end())
        {
            if((*it)->GetSeatPosition() == proto::SeatPosition::Right);
            {
                if(!IsGiveUp((*it)->GetId()))
                {
                    return (*it);
                }
                else
                {
                    GetNextPlayer(proto::SeatPosition::Right);
                }
            }
            it++;
        } 
    }
    else if(seatPosition == proto::SeatPosition::Right)
    {
        auto it = m_players.begin();
        while(it != m_players.end())
        {
            if((*it)->GetSeatPosition() == proto::SeatPosition::Left && !IsGiveUp((*it)->GetId()))
            {
                if(!IsGiveUp((*it)->GetId()))
                {
                    return (*it);
                }
                else
                {
                    GetNextPlayer(proto::SeatPosition::Left);
                }
            }
            it++;
        } 
    }
    else
    {
        auto it = m_players.begin();
        while(it != m_players.end())
        {
            if((*it)->GetSeatPosition() == proto::SeatPosition::Middle && !IsGiveUp((*it)->GetId()))
            {
                if(!IsGiveUp((*it)->GetId()))
                {
                    return (*it);
                }
                else
                {
                    GetNextPlayer(proto::SeatPosition::Middle);
                }
            }
            it++;
        }
    }
    return (*m_players.begin());
}

void MatchRoom::ClearRoom()
{
    m_banker.reset();
    m_players.clear();
    m_alreadyPlayers.clear();
    m_remainSeats.clear();
    m_remainSeats.push_back(proto::SeatPosition::Left);
    m_remainSeats.push_back(proto::SeatPosition::Middle);
    m_remainSeats.push_back(proto::SeatPosition::Right);
}

Player::ptr MatchRoom::GetPlayer(proto::SeatPosition seatPosition)
{
    auto it = m_players.begin();
    while(it != m_players.end())
    {
        if((*it)->GetSeatPosition() == seatPosition)
        {
            return (*it);
        }
        it++;
    }
    return nullptr;
}

void MatchRoom::AddToGiveUp(int playerId)
{
    if(IsGiveUp(playerId))
    {
        return;
    }
    m_giveUpCards.push_back(playerId);
}

bool MatchRoom::IsGiveUp(int playerId)
{
    return std::count(m_giveUpCards.begin(), m_giveUpCards.end(), playerId) == 1;
}

int RoomManager::roomIdSeed = 0;

MatchRoom::ptr RoomManager::Enter(Player::ptr& player, proto::RoomType roomType)
{
    if(m_UnFullRooms.size() > 0)
    {
        auto it = m_UnFullRooms.begin();
        while(it != m_UnFullRooms.end())
        {
            if(it->second->GetRoomType() == roomType)
            {
                it->second->Enter(player);
                player->SetPosition(it->second->DistributionSeat());
                m_playerInRoom[player->GetId()] = m_UnFullRooms.begin()->first;
                if(it->second->IsFull())
                {
                    int roomId = it->first;
                    MatchRoom::ptr matchRoom = it->second;
                    m_FullRooms[roomId] = matchRoom;
                    m_UnFullRooms.erase(roomId);
                }
                return it->second;
            }
            it++;
        }
    }
    MatchRoom::ptr matchRoom(new MatchRoom(++roomIdSeed));
    matchRoom->SetRoomType(roomType);
    m_UnFullRooms[roomIdSeed] = matchRoom;
    matchRoom->Enter(player);
    player->SetPosition(matchRoom->DistributionSeat());
    m_playerInRoom[player->GetId()] = matchRoom->GetRoomId();
    return matchRoom;
}

MatchRoom::ptr RoomManager::Leave(Player::ptr& player)
{
    int playerId = player->GetId();
    int roomId = m_playerInRoom[playerId];
    m_playerInRoom.erase(playerId);
    if(m_UnFullRooms.count(roomId) != 0)
    {
        m_UnFullRooms[roomId]->Leave(playerId);
        m_UnFullRooms[roomId]->RecycleSeat(player->GetSeatPosition());
        return m_UnFullRooms[roomId];
    }
    else if(m_FullRooms.count(roomId) != 0)
    {
        MatchRoom::ptr room = m_FullRooms[roomId];
        room->Leave(playerId);
        m_UnFullRooms[room->GetRoomId()] = room;
        room->RecycleSeat(player->GetSeatPosition());
        m_FullRooms.erase(roomId);
        return m_UnFullRooms[roomId];
    }
    LOG_ERROR(lvqiang) << "没有找到要离开的房间";
    return nullptr;
}

MatchRoom::ptr RoomManager::GetRoom(Player::ptr& player)
{
    int playerId = player->GetId();
    int roomId = m_playerInRoom[playerId];
    if(m_UnFullRooms.count(roomId) != 0)
    {
        return m_UnFullRooms[roomId];
    }
    else if(m_FullRooms.count(roomId) != 0)
    {
        return m_UnFullRooms[roomId];
    }
    return nullptr;
}

















